#include "gui.h"
#include "gui_button.h"
#include"gui_checkbox.h"
#include"gui_list.h"
#include <stdio.h>
#include <stddef.h>

static gui_cursor_info_t cursor_info[] = {
    {"normal", -7, -7},
    {"hold", -14, -14},
    {"help", -7, -7},
    {"pen", -14, -14},
    {"busy", -7, -7},
    {"accurate", -14, -14},
    {"text", -2, -11},
    {"unusable", -14, -14},
    {"vresize", -14, -14},
    {"hresize", -14, -14},
    {"dresize1", -14, -14},
    {"dresize2", -14, -14},
    {"resizeall", -14, -14},
    {"hand", -11, -8},
    {"invisible",-7,-7}
};

int gui_mouse_motion(gui_spirit_t *spirit, int x, int y)
{
    gui_container_t *container = spirit->container;
    if (!container)
        return -1;
    gui_spirit_t *tmp;

    list_traversal_all_owner_to_next(tmp, &container->children_list, list)
    {
        if (!tmp->visiable)
            continue;
        switch (tmp->type)
        {
        case GUI_SPIRIT_TYPE_LABEL:
            break;
        case GUI_SPIRIT_TYPE_BOX:
        {
            gui_box_t *box=GUI_BOX(tmp);
            if(GUI_IN_SPIRIT(tmp,x,y))
            {
                //box container filter sucessful return 0,
                //otherwise continue processing
                if(!gui_mouse_motion(tmp,x,y))  
                    return 0;
            }
        }
        case GUI_SPIRIT_TYPE_BUTTON:
        {
            gui_button_t *button = GUI_BUTTON(tmp);
            if (button->disable)
            {
                break;
            }

            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                uview_set_mouse_status(spirit->view, tmp->style.cursor);
                if (button->status == GUI_BUTTON_IDLE)
                {
                    gui_signal_emit_by_name(tmp, "enter_notify");
                    gui_button_change_status(button, GUI_BUTTON_TOUCH);
                }
            }
            else
            {
                if (button->status != GUI_BUTTON_IDLE)
                {
                    gui_button_change_status(button, GUI_BUTTON_IDLE);
                    uview_set_mouse_status(spirit->view, GUI_CURSOR_NORMAL);
                    gui_signal_emit_by_name(tmp, "leave_notify");
                }
            }
        }
        break;
        case GUI_SPIRIT_TYPE_ENTRY:
        {
            gui_entry_t *entry = GUI_ENTRY(tmp);
            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                gui_entry_mouse_motion(entry, x - tmp->x);
            }
        }
        break;
        case GUI_SPIRIT_TYPE_SCROLLBAR:
        {
            gui_scrollbar_t *scrollbar = GUI_SCROLLBAR(tmp);
            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                gui_scrollbar_mouse_motion(scrollbar, x - tmp->x, y - tmp->y);
                return 0;
            }
        }
        break;
        case GUI_SPIRIT_TYPE_SWITCH:
        {
            gui_switch_t *switch_obj = GUI_SWITCH(tmp);
            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                gui_switch_mouse_motion(switch_obj, x, y);
                return 0;
            }
        }
        break;
        case GUI_SPIRIT_TYPE_SELECT:
        {
            gui_select_t *select = GUI_SELECT(tmp);
            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                gui_select_mouse_motion(select, x, y);
                return 0;
            }
        }
        break;
        case GUI_SPIRIT_TYPE_LIST:
        {
            gui_list_t *list=GUI_LIST(tmp);
            if(GUI_IN_SPIRIT(tmp,x,y))
            {
                gui_list_mouse_motion(list,x,y);
                return 0;
            }
        }
        break;
        default:
            break;
        }
    }
    return -1;
}

int gui_mouse_btn_down(gui_spirit_t *spirit, int btn, int x, int y)
{
    gui_container_t *container = spirit->container;
    if (!container)
        return -1;

    gui_spirit_t *tmp;
    list_traversal_all_owner_to_next(tmp, &container->children_list, list)
    {
        if (!tmp->visiable)
            continue;
        switch (tmp->type)
        {
        case GUI_SPIRIT_TYPE_LABEL:
            break;
        case GUI_SPIRIT_TYPE_BOX:
        {
            gui_box_t *box=GUI_BOX(tmp);
            if(GUI_IN_SPIRIT(tmp,x,y))
            {
                gui_mouse_btn_down(&box->spirit,btn,x,y);
                return 0;
            }
        }
        break;
        case GUI_SPIRIT_TYPE_BUTTON:
        {
            if (btn != UVIEW_BTN_LEFT)
                break;

            gui_button_t *button = GUI_BUTTON(tmp);
            if (button->disable)
                break;

            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                uview_set_mouse_status(spirit->view, UVIEW_MOUSE_NORMAL);
                if (button->status == GUI_BUTTON_TOUCH)
                {
                    gui_signal_emit_by_name(tmp, "button_press");
                    gui_button_change_status(button, GUI_BUTTON_CLICK);
                    return 0;
                }
            }
            else
            {
                if (button->status == GUI_BUTTON_TOUCH)
                {
                    gui_signal_emit_by_name(tmp, "button_press");
                    gui_button_change_status(button, GUI_BUTTON_CLICK);
                    return 0;
                }
            }
        }
        break;
        case GUI_SPIRIT_TYPE_ENTRY:
        {
            if (btn != UVIEW_BTN_LEFT)
                break;
            gui_entry_t *entry = GUI_ENTRY(tmp);
            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                gui_entry_set_focus(entry, true);
                gui_entry_mouse_press(entry, x - tmp->x);
                return 0;
            }
            else
            {
                gui_entry_set_focus(entry, false);
            }
        }
        break;
        case GUI_SPIRIT_TYPE_SWITCH:
        {
            gui_switch_t *switch_obj = GUI_SWITCH(tmp);
            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                gui_switch_mouse_press(switch_obj, btn, x, y);
                return 0;
            }
        }
        break;
        case GUI_SPIRIT_TYPE_SELECT:
        {
            gui_select_t *select = GUI_SELECT(tmp);
            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                gui_select_mouse_press(select, btn, x, y);
                return 0;
            }
        }
        break;
        case GUI_SPIRIT_TYPE_LIST:
        {
            gui_list_t *list=GUI_LIST(tmp);
            if(GUI_IN_SPIRIT(tmp,x,y))
            {
                gui_list_mouse_press(list,btn,x,y);
                return 0;
            }
        }
        break;
        default:
            break;
        }
    }
    return -1;
}

int gui_mouse_btn_up(gui_spirit_t *spirit, int btn, int x, int y)
{
    gui_container_t *container = spirit->container;
    if (!container)
        return -1;
    gui_spirit_t *tmp;
    list_traversal_all_owner_to_next(tmp, &container->children_list, list)
    {
        if (!tmp->visiable)
            continue;
        switch (tmp->type)
        {
        case GUI_SPIRIT_TYPE_LABEL:
            break;
        case GUI_SPIRIT_TYPE_BOX:
        {
            gui_box_t *box=GUI_BOX(tmp);
            if(GUI_IN_SPIRIT(tmp,x,y))
            {
                gui_mouse_btn_up(&box->spirit,btn,x,y);
                return 0;
            }
            break;
        }
        case GUI_SPIRIT_TYPE_BUTTON:
        {
            if (btn != UVIEW_BTN_LEFT)
                break;

            gui_button_t *button = GUI_BUTTON(tmp);
            if (button->disable)
                break;

            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                uview_set_mouse_status(spirit->view, tmp->style.cursor);
                if (button->status == GUI_BUTTON_CLICK)
                {
                    gui_button_change_status(button, GUI_BUTTON_TOUCH);
                    gui_signal_emit_by_name(tmp, "button_release");
                    return 0;
                }
            }
        }
        break;
        case GUI_SPIRIT_TYPE_ENTRY:
        {
            if (btn != UVIEW_BTN_LEFT)
                break;
            gui_entry_t *entry = GUI_ENTRY(tmp);
            gui_entry_mouse_release(entry);
            return 0;
        }
        break;
        case GUI_SPIRIT_TYPE_SWITCH:
        {
            gui_switch_t *switch_obj = GUI_SWITCH(tmp);
            if (GUI_IN_SPIRIT(tmp, x, y))
            {
                gui_switch_mouse_release(switch_obj, btn, x, y);
                return 0;
            }
        }
        break;
        case GUI_SPIRIT_TYPE_SELECT:
        {
            gui_select_t *select=GUI_SELECT(tmp);
            if(GUI_IN_SPIRIT(tmp,x,y))
            {
                gui_select_mouse_release(select,btn,x,y);
                return 0;
            }
        }
        break;
        case GUI_SPIRIT_TYPE_LIST:
        {
            gui_list_t *list=GUI_LIST(tmp);
            if(GUI_IN_SPIRIT(tmp,x,y))
            {
                gui_list_mouse_release(list,btn,x,y);
                return 0;
            }
        }
        break;
        default:
            break;
        }
    }
    return -1;
}

int gui_mouse_load_cursor(int view, char *path, uview_mouse_status_t status, int off_x, int off_y)
{
    gui_image_t *img = gui_image_load2(path, 32, 32);
    if (!img)
        return -1;
    uview_bitmap_t bmp;
    uview_bitmap_init(&bmp, img->w, img->h, (uview_color_t *)img->buff);
    uview_mouse_status_info_t info;
    info.bmp = &bmp;
    info.off_x = off_x;
    info.off_y = off_y;
    info.status = status;
    if (uview_set_mouse_status_info(view, &info) < 0)
    {
        free(img);
        return -1;
    }
    //set to normal status,redraw cursor
    uview_set_mouse_status(view,GUI_CURSOR_NORMAL);
    free(img);
    return 0;
}

void gui_mouse_load_cursors(int view, const char *path)
{
    uview_mouse_status_t mstu;
    char file[MAX_PATH_LEN+1];
    for (mstu = 0; mstu < UVIEW_MOUSE_STATUS_NUM; mstu++)
    {
        memset(file, 0, MAX_PATH_LEN);
        strcpy(file, path);
        strcat(file, "/");
        strcat(file, cursor_info[mstu].path);
        strcat(file, ".png");
        dprintf("cursor path %s\n",file);
        if (gui_mouse_load_cursor(view, file, mstu, cursor_info[mstu].off_x, cursor_info[mstu].off_y) < 0)
            printf("mouse load cursor %s failed!\n", file);
    }
}